package com.fenyin.samples.study.jdk.nio.channels.tcp.server;  

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.Iterator;
  
/**
 * 该类存在错误，请修正
 *@Title:  
 *@Description:  
 *@Author:fengzhichao  
 *@Since:2012-12-13  
 *@Version:1.1.0
 */
public class Server extends Thread{
	private static final int SERVERPORT=19997;
	private Selector selector = null;
	private ServerSocketChannel serverSocketChannel = null; 
	private SocketChannel socketChannel;
	
	public Server(){
		try{
			//创建通道监听器
			selector = Selector.open();
			//创建ServerSocket通道
			serverSocketChannel = ServerSocketChannel.open();
			//绑定端口
			serverSocketChannel.socket().bind(new InetSocketAddress(SERVERPORT));
			//设置非阻塞模式
			serverSocketChannel.configureBlocking(false);
			//ServerSocket通道绑定通道监听器
			serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT);
			System.out.println("服务器开始接受客户端连接");
			
		}catch(IOException e){
			e.printStackTrace();
		}
	}
	
	public void run(){
		try{
			while(true){
				//选择监听事件
				selector.select();
				//选择器定时轮询，并处理
				Iterator<SelectionKey>it = selector.selectedKeys().iterator();
				//循环处理监听事件
				while(it.hasNext()){
					SelectionKey key = it.next();
					it.remove();
					if(key.isAcceptable()){
						//接收事件处理
						socketChannel = serverSocketChannel.accept();
						socketChannel.configureBlocking(false);
						socketChannel.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
						System.out.println("客户端："+ socketChannel.socket().getInetAddress().getHostName() + ":"+ socketChannel.socket().getPort() + " 连接上了");
					}
//					readable
					if(key.isReadable()){
						//可读事件处理
						CharsetDecoder decoder = Charset.forName("UTF-8").newDecoder();
						ByteBuffer buffer = ByteBuffer.allocate(50);
						try{
							socketChannel.read(buffer);
						}catch(IOException e){
//							客户端异常断开连接
							System.out.println("客户端："+ socketChannel.socket().getInetAddress().getHostName() + ":"+ socketChannel.socket().getPort() + " 已断开连接");
							socketChannel.close();
							continue;
						}
						buffer.flip();
						String msg = decoder.decode(buffer).toString();

						if (msg.equals("退出!@#$%")) {
//							客户端主动断开连接
							System.out.println("客户端："+ socketChannel.socket().getInetAddress().getHostName() + ":"+ socketChannel.socket().getPort() + " 已断开连接");
							socketChannel.close();
							continue;
						}
						//输出接受到的内容
						System.out.println(socketChannel.socket().getInetAddress().getHostName() + ":"+ socketChannel.socket().getPort() + "：" + msg);
						
						if (key.isWritable()) {
//							//可写事件处理
							CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
							try {
								socketChannel.write(encoder.encode(CharBuffer.wrap("server receive your message ")));
							} catch (IOException e) {
								System.out.println("写入io错误");
							}
						}
					}
				}
			}
		}catch(IOException e){
			e.printStackTrace();
		}
		finally{
			try{
				selector.close();
				serverSocketChannel.close();
			}catch(IOException e){}
		}
	
	}
	
	public static void main(String[] args) {
		new Server().start();
	}
}
